package fr.upstlse.glre.server.controler;

import java.util.ArrayList;
import java.util.List;

import com.google.gwt.user.client.ui.SuggestOracle;
import com.google.gwt.user.client.ui.MultiWordSuggestOracle.MultiWordSuggestion;
import com.google.gwt.user.client.ui.SuggestOracle.Request;
import com.google.gwt.user.client.ui.SuggestOracle.Response;
import com.google.gwt.user.server.rpc.RemoteServiceServlet;

import fr.upstlse.glre.business.ServiceLocator;
import fr.upstlse.glre.business.service.communiquer.BoiteAuxLettresService;
import fr.upstlse.glre.business.service.communiquer.MessageService;
import fr.upstlse.glre.business.service.user.EtudiantService;
import fr.upstlse.glre.business.service.user.ProfesseurService;
import fr.upstlse.glre.business.service.user.UserService;
import fr.upstlse.glre.business.vo.communiquer.BoiteAuxLettresVO;
import fr.upstlse.glre.business.vo.communiquer.MessageVO;
import fr.upstlse.glre.business.vo.user.EtudiantSearchCriteriaVO;
import fr.upstlse.glre.business.vo.user.EtudiantVO;
import fr.upstlse.glre.business.vo.user.ProfesseurVO;
import fr.upstlse.glre.business.vo.user.UserSearchCriteriaVO;
import fr.upstlse.glre.business.vo.user.UserVO;
import fr.upstlse.glre.client.controler.UserControlerService;
import fr.upstlse.glre.client.vo.communiquer.BoiteAuxLettresVOGWT;
import fr.upstlse.glre.client.vo.communiquer.MessageVOGWT;
import fr.upstlse.glre.client.vo.user.EtudiantSearchCriteriaVOGWT;
import fr.upstlse.glre.client.vo.user.EtudiantVOGWT;
import fr.upstlse.glre.client.vo.user.ProfesseurVOGWT;
import fr.upstlse.glre.client.vo.user.UserSearchCriteriaVOGWT;
import fr.upstlse.glre.client.vo.user.UserVOGWT;
import fr.upstlse.glre.server.util.VOUtil;

public class UserControlerServiceImpl extends RemoteServiceServlet implements
		UserControlerService {

	/**
	 * 
	 */
	private static final long serialVersionUID = -4162588882511003821L;

	private ServiceLocator serviceLocator;
	private UserService userService;
	private EtudiantService etudiantService;
	private ProfesseurService professeurService;
	private BoiteAuxLettresService boiteAuxLettresService;
	private MessageService messageService;

	public UserControlerServiceImpl() {
		serviceLocator = ServiceLocator.instance();
		userService = serviceLocator.getUserService();
		etudiantService = serviceLocator.getEtudiantService();
		professeurService = serviceLocator.getProfesseurService();
		boiteAuxLettresService = serviceLocator.getBoiteAuxLettresService();
		messageService = serviceLocator.getMessageService();
	}

	public List<EtudiantVOGWT> findEtudiant(EtudiantSearchCriteriaVOGWT pEtudiantSearchCriteriaVOGWT) {
		EtudiantSearchCriteriaVO lEtudiantSearchCriteriaVO = VOUtil.etudiantSearchCriteriaVOGWTToEtudiantSearchCriteriaVO(pEtudiantSearchCriteriaVOGWT);

		List<EtudiantVO> lEtudiants = etudiantService.findEtudiant(lEtudiantSearchCriteriaVO);
		
		List<EtudiantVOGWT> lEtudiantVOGWTs = new ArrayList<EtudiantVOGWT>(lEtudiants.size());
		
		for(EtudiantVO lEtudiantVO : lEtudiants) {
			EtudiantVOGWT lEtudiantVOGWT = VOUtil.etudiantVOToEtudiantVOGWT(lEtudiantVO);
			lEtudiantVOGWTs.add(lEtudiantVOGWT);
		}
		return lEtudiantVOGWTs;
	}

	public List<UserVOGWT> findUser(UserSearchCriteriaVOGWT pUserSearchCriteriaVOGWT) {
		UserSearchCriteriaVO lUserSearchCriteriaVO = VOUtil.userSearchCriteriaVOGWTToUserSearchCriteriaVO(pUserSearchCriteriaVOGWT);

		List<UserVO> lUserFinded = userService.findUser(lUserSearchCriteriaVO);

		List<UserVOGWT> lUserVOGWTs = new ArrayList<UserVOGWT>(lUserFinded.size());
		
		for(UserVO lUserVO : lUserFinded) {
			UserVOGWT lUserVOGWT = VOUtil.userVOToUserVOGWT(lUserVO);
			lUserVOGWTs.add(lUserVOGWT);
		}
 		return lUserVOGWTs;
	}

	public void updateEtudiant(EtudiantVOGWT pEtudiant) {
		EtudiantVO lEtudiant = VOUtil.etudiantVOGWTToEtudiantVO(pEtudiant);
		etudiantService.updateEtudiant(lEtudiant);
	}


	public EtudiantVOGWT getEtudiantById(long pEtudiantId) {
		EtudiantVO lEtudiantVO = etudiantService.getById(pEtudiantId);
		EtudiantVOGWT lEtudiantVOGWT = VOUtil.etudiantVOToEtudiantVOGWT(lEtudiantVO);
		return lEtudiantVOGWT;
	}

	public long createEtudiant(EtudiantVOGWT etudiantVOGWT) {
		EtudiantVO lEtudiantVO = VOUtil.etudiantVOGWTToEtudiantVO(etudiantVOGWT);
		EtudiantVO lCreatedEtudiantVO = etudiantService.createAndGet(lEtudiantVO);
		createBoiteAuxLettres(lCreatedEtudiantVO);
		return lCreatedEtudiantVO.getId();
	}
	
	private void createBoiteAuxLettres(UserVO pUserVO) {
		BoiteAuxLettresVO lBoiteAuxLettresVO = new BoiteAuxLettresVO();
		lBoiteAuxLettresVO.setProprietaire(pUserVO);
		boiteAuxLettresService.create(lBoiteAuxLettresVO);
	}

	public void updateUser(UserVOGWT pUserVOGWT) {
		UserVO lUserVO = VOUtil.userVOGWTToUserVO(pUserVOGWT);
		userService.updateUser(lUserVO);
		
	}

	public long createProfesseur(ProfesseurVOGWT professeurVOGWT) {
		ProfesseurVO lProfesseurVO = VOUtil.professeurVOGWTToProfesseurVO(professeurVOGWT);
		ProfesseurVO lCreatedProfesseurVO = professeurService.createAndGet(lProfesseurVO);
		createBoiteAuxLettres(lCreatedProfesseurVO);
		return lCreatedProfesseurVO.getId();
	}

	public long createUser(UserVOGWT userVOGWT) {
		UserVO lUserVO = VOUtil.userVOGWTToUserVO(userVOGWT);
		UserVO lCreatedUserVO = userService.createAndGetUser(lUserVO);
		createBoiteAuxLettres(lCreatedUserVO);
		return lCreatedUserVO.getId();
	}

	public List<UserVOGWT> getAllUser() {
		List<UserVO> lUserVOs = userService.getAllUsers();
		ArrayList<UserVOGWT> lUserVOGWTs = new ArrayList<UserVOGWT>(lUserVOs.size());
		for(UserVO lUserVO : lUserVOs) {
			UserVOGWT lUserVOGWT = VOUtil.userVOToUserVOGWT(lUserVO);
			lUserVOGWTs.add(lUserVOGWT);
		}
		return lUserVOGWTs;
	}

	public void updateProfesseur(ProfesseurVOGWT professeurVOGWT) {
		ProfesseurVO lProfesseurVO = VOUtil.professeurVOGWTToProfesseurVO(professeurVOGWT);
		professeurService.updateProfesseur(lProfesseurVO);
	}

	public ProfesseurVOGWT getProfesseurById(long professeurId) {
		ProfesseurVO lProfesseurVO = professeurService.getById(professeurId);
		ProfesseurVOGWT lProfesseurVOGWT = VOUtil.professeurVOToProfesseurVOGWT(lProfesseurVO);
		return lProfesseurVOGWT;
	}

	public void deleteUser(UserVOGWT userVOGWT) {
		UserVO lUserVO = VOUtil.userVOGWTToUserVO(userVOGWT);
		userService.deleteUser(lUserVO);
	}

	public UserVOGWT getUserById(long userId) {
		UserVO lUserVO = userService.getById(userId);
		UserVOGWT lUserVOGWT = null;
		if(lUserVO != null) {
			lUserVOGWT = VOUtil.userVOToUserVOGWT(lUserVO);
		}
		
		return lUserVOGWT;
	}

	public UserVOGWT login(String pLogin, String pPassword) {
		UserSearchCriteriaVO lUserSearchCriteriaVO = new UserSearchCriteriaVO(
				pLogin, pPassword);

		List<UserVO> lUserFinded = userService.findUser(lUserSearchCriteriaVO);
		
		if(! lUserFinded.isEmpty()) {
			return VOUtil.userVOToUserVOGWT(lUserFinded.get(0));
		}
		else {
			return new UserVOGWT();
		}
			
	}

	public List<UserVOGWT> findEtudiantUser(
			EtudiantSearchCriteriaVOGWT etudiantSearchCriteriaVOGWT) {
		List<EtudiantVOGWT> lEtudiantVOGWTs = findEtudiant(etudiantSearchCriteriaVOGWT);
		ArrayList<UserVOGWT> lUserVOGWTs = new ArrayList<UserVOGWT>(lEtudiantVOGWTs.size());
		for(EtudiantVOGWT lEtudiantVOGWT : lEtudiantVOGWTs) {
			UserVOGWT lUserVOGWT = VOUtil.etudiantVOGWTToUserVOGWT(lEtudiantVOGWT);
			lUserVOGWTs.add(lUserVOGWT);
		}
		return lUserVOGWTs;
	}

	public List<UserVOGWT> findByNom(String nom) {
		// TODO Auto-generated method stub
		return null;
	}
	
	public BoiteAuxLettresVOGWT findByProprietaire(UserVOGWT pUserVOGWT) {
		BoiteAuxLettresVO lBoiteAuxLettresVO = boiteAuxLettresService.findByProprietaireId(pUserVOGWT.getId());
		BoiteAuxLettresVOGWT lBoiteAuxLettresVOGWT = VOUtil.createBoiteAuxLettresVOGWT(lBoiteAuxLettresVO);
		for(MessageVOGWT lMessageVOGWT : lBoiteAuxLettresVOGWT.getMessages()) {
			lMessageVOGWT.setFils(getFils(lMessageVOGWT));
		}
		return lBoiteAuxLettresVOGWT;
	}

	public void envoyer(MessageVOGWT pMessageVOGWT, List<String> pDestinataires) {
		MessageVO lMessageVO = VOUtil.createMessageVO(pMessageVOGWT);
		messageService.envoyer(lMessageVO, pDestinataires);
	}

	public Response getEmails(Request pRequest) {
		UserSearchCriteriaVOGWT lUserSearchCriteriaVOGWT = new UserSearchCriteriaVOGWT();
		lUserSearchCriteriaVOGWT.setLogin(pRequest.getQuery() + "%");
		
		List<UserVOGWT> lUserVOGWTs = findUser(lUserSearchCriteriaVOGWT);
		List<MultiWordSuggestion> lEmails = new ArrayList<MultiWordSuggestion>(pRequest.getLimit());
		for(UserVOGWT lUserVOGWT : lUserVOGWTs) {
			lEmails.add(new MultiWordSuggestion(lUserVOGWT.getLogin(), lUserVOGWT.getLogin()));
		}
		
		SuggestOracle.Response lResponse = new SuggestOracle.Response();
		lResponse.setSuggestions(lEmails);
		
		return lResponse;
	}

	public UserVOGWT findByLogin(String pLogin) {
		UserVO lUserVO = userService.findByLogin(pLogin);
		UserVOGWT lUserVOGWT = null;
		if(lUserVO != null) {
			lUserVOGWT = VOUtil.userVOToUserVOGWT(lUserVO);
		}
		return lUserVOGWT;
	}

	public MessageVOGWT findMessageById(long pMesssageId) {
		MessageVO lMessageVO = messageService.findById(pMesssageId);
		MessageVOGWT lMessageVOGWT = VOUtil.createMessageVOGWT(lMessageVO);
		lMessageVOGWT.setFils(getFils(lMessageVOGWT));
		return lMessageVOGWT;
	}

	public void repondre(MessageVOGWT pMessageVOGWT, MessageVOGWT pReponse) {
		MessageVO lMessageVO = VOUtil.createMessageVO(pMessageVOGWT);
		MessageVO lReponse = VOUtil.createMessageVO(pReponse);
		messageService.repondre(lMessageVO, lReponse);
	}
	
	private MessageVOGWT getFils(MessageVOGWT pParent) {
		MessageVO lFils = messageService.findFils(VOUtil.createMessageVO(pParent));
		MessageVOGWT lFilsMessageVOGWT = VOUtil.createMessageVOGWT(lFils);
		return lFilsMessageVOGWT;
	}

	public void updateMessage(MessageVOGWT pMessageVOGWT) {
		MessageVO lMessageVO = VOUtil.createMessageVO(pMessageVOGWT);
		messageService.updateMessage(lMessageVO);
	}
}